package com.roads.plan.service.impl;

import com.roads.common.constant.Constants;
import com.roads.common.core.domain.entity.SysUser;
import com.roads.common.exception.ServiceException;
import com.roads.common.utils.DateUtils;
import com.roads.common.utils.SecurityUtils;
import com.roads.common.utils.StringUtils;
import com.roads.common.utils.uuid.IdUtils;
import com.roads.plan.domain.PlanProfileBoq;
import com.roads.plan.domain.PlanProfileScheduleDetail;
import com.roads.plan.domain.PlanProfileScheduleMaster;
import com.roads.plan.mapper.PlanProfileBoqMapper;
import com.roads.plan.mapper.PlanProfileScheduleDetailMapper;
import com.roads.plan.mapper.PlanProfileScheduleMasterMapper;
import com.roads.plan.service.IPlanProfileScheduleService;
import com.roads.project.domain.ProCompany;
import com.roads.project.domain.ProInstitution;
import com.roads.project.domain.ProProject;
import com.roads.project.mapper.ProCompanyMapper;
import com.roads.project.mapper.ProInstitutionMapper;
import com.roads.project.mapper.ProProjectMapper;
import com.roads.system.mapper.SysUserMapper;
import com.roads.system.service.ISysMessageService;
import com.roads.workflow.domain.WorkflowMeterageNode;
import com.roads.workflow.domain.WorkflowTaskDelivery;
import com.roads.workflow.mapper.WorkflowMeterageNodeMapper;
import com.roads.workflow.service.IWorkflowTaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 形象进度Service实现类
 *
 * @author nhp
 * @date 2024-03-05
 */
@Service
public class PlanProfileScheduleServiceImpl implements IPlanProfileScheduleService {

    @Autowired
    private PlanProfileScheduleMasterMapper masterMapper;

    @Autowired
    private PlanProfileScheduleDetailMapper detailMapper;

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private WorkflowMeterageNodeMapper workflowMeterageNodeMapper;

    @Autowired
    private ProInstitutionMapper institutionMapper;

    @Autowired
    private ProProjectMapper projectMapper;

    @Autowired
    private ProCompanyMapper companyMapper;

    @Autowired
    private IWorkflowTaskService workflowTaskService;

    @Autowired
    private PlanProfileBoqMapper planProfileBoqMapper;

    @Autowired
    private ISysMessageService messageService;

    /**
     * 根据主键ID查询主表详情
     *
     * @param id 形象进度主表主键
     * @return 形象进度
     */
    @Override
    public PlanProfileScheduleMaster getMasterById(Integer id) {
        return masterMapper.getModelById(id);
    }

    /**
     * 根据主键ID查询明细详情
     *
     * @param id 形象进度明细主键
     * @return 形象进度
     */
    @Override
    public PlanProfileScheduleDetail getDetailById(Integer id) {
        return detailMapper.getModelById(id);
    }

    /**
     * 查询列表
     *
     * @param model 形象进度主表
     * @return 形象进度集合
     */
    @Override
    public List<PlanProfileScheduleMaster> selectMasterList(PlanProfileScheduleMaster model) {
        return masterMapper.selectModelList(model);
    }

    /**
     * 查询详细列表
     *
     * @param model 形象进度明细
     * @return 形象进度明细集合
     */
    @Override
    public List<PlanProfileScheduleDetail> selectDetailList(PlanProfileScheduleDetail model) {
        return detailMapper.selectModelList(model);
    }

    /**
     * 批量锁定
     *
     * @param ids 主键集合
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int lock(Integer[] ids) {
        SysUser loginUser = userMapper.selectUserById(SecurityUtils.getUserId());
        // 循环处理锁定数据
        for (int i = 0; i < ids.length; i++) {
            int masterId = ids[i];
            // 主表状态处理
            PlanProfileScheduleMaster master = masterMapper.getModelById(masterId);
            master.setStatus(Constants.LOCK);
            masterMapper.update(master);
            // 完成流程处理
            workflowTaskService.finishTask(master.getUuid(), loginUser);
            // 消息处理
            messageService.handleDeliveryMessage(master.getUuid(), loginUser.getUserName());
            // 更新形象计划清单
            PlanProfileScheduleDetail searchDetail = new PlanProfileScheduleDetail();
            searchDetail.setMasterId(masterId);
            searchDetail.setUser(master.getCurrentUser());
            List<PlanProfileScheduleDetail> details = detailMapper.selectModelList(searchDetail);
            Map<String, PlanProfileScheduleDetail> maps = new HashMap<>();
            for (PlanProfileScheduleDetail detail: details) {
                maps.put(detail.getInstitutionBoqCode(), detail);
            }
            // 更新形象清单
            updateProfileBoq(maps, master.getInstitutionCode(), true);
        }
        return 1;
    }

    /**
     * 修改形象清单的工程量、产值
     *
     * @param maps 形象进度详情列表
     * @param institutionCode 标段编号
     */
    private void updateProfileBoq(Map<String, PlanProfileScheduleDetail> maps, String institutionCode, boolean flag) {
        PlanProfileBoq search = new PlanProfileBoq();
        search.setInstitutionCode(institutionCode);
        List<PlanProfileBoq> list = planProfileBoqMapper.selectModelList(search);
        for (PlanProfileBoq boq : list) {
            PlanProfileScheduleDetail detail = maps.get(boq.getInstitutionBoqCode());
            if (StringUtils.isNotNull(detail)) {
                if (Constants.YES.equals(boq.getLeafNode())) {
                    BigDecimal alreadyAmount = boq.getAlreadyAmount() == null ? BigDecimal.ZERO : boq.getAlreadyAmount();
                    BigDecimal remainderAmount = boq.getRemainderAmount() == null ? BigDecimal.ZERO : boq.getRemainderAmount();
                    BigDecimal alreadyTotal = boq.getAlreadyTotal() == null ? BigDecimal.ZERO : boq.getAlreadyTotal();
                    BigDecimal remainderTotal = boq.getRemainderTotal() == null ? BigDecimal.ZERO : boq.getRemainderTotal();
                    BigDecimal amount = detail.getAmount() == null ? BigDecimal.ZERO : detail.getAmount();
                    BigDecimal total = detail.getTotal() == null ? BigDecimal.ZERO : detail.getTotal();
                    if (flag) {
                        alreadyAmount = alreadyAmount.add(amount);
                        remainderAmount = remainderAmount.subtract(amount);
                        alreadyTotal = alreadyTotal.add(total);
                        remainderTotal = remainderTotal.subtract(total);
                        if (remainderAmount.compareTo(BigDecimal.ZERO) < 0) {
                            boq.setComplete(Constants.YES);
                        }
                    } else {
                        alreadyAmount = alreadyAmount.subtract(amount);
                        remainderAmount = remainderAmount.add(amount);
                        alreadyTotal = alreadyTotal.subtract(total);
                        remainderTotal = remainderTotal.add(total);
                        if (remainderAmount.compareTo(BigDecimal.ZERO) > 0) {
                            boq.setComplete(Constants.NO);
                        }
                    }
                    boq.setAlreadyAmount(alreadyAmount);
                    boq.setRemainderAmount(remainderAmount);
                    boq.setAlreadyTotal(alreadyTotal);
                    boq.setRemainderTotal(remainderTotal);
                }
            }
        }
        planProfileBoqMapper.updateBatch(list);
    }

    /**
     * 解锁
     *
     * @param master 主表
     * @param id 主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int unlock(PlanProfileScheduleMaster master, Integer id) {
        // 更新状态
        master.setStatus(Constants.UNLOCK);
        masterMapper.update(master);
        // 还原形象清单
        PlanProfileScheduleDetail searchDetail = new PlanProfileScheduleDetail();
        searchDetail.setMasterId(master.getMasterId());
        searchDetail.setUser(master.getCurrentUser());
        List<PlanProfileScheduleDetail> details = detailMapper.selectModelList(searchDetail);
        Map<String, PlanProfileScheduleDetail> maps = new HashMap<>();
        for (PlanProfileScheduleDetail detail: details) {
            maps.put(detail.getInstitutionBoqCode(), detail);
        }
        // 还原形象清单
        updateProfileBoq(maps, master.getInstitutionCode(), false);
        return 1;
    }

    /**
     * 新增
     *
     * @param model 形象进度
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insert(PlanProfileScheduleMaster model) {
        SysUser loginUser = userMapper.selectUserById(SecurityUtils.getUserId());
        // 获取流程实例
        WorkflowMeterageNode workflowMeterageNode = workflowMeterageNodeMapper.getModelByBeginNodeAndUser(loginUser.getUserName(), Constants.WORKFLOW_TYPE_PROFILE);
        if (StringUtils.isNull(workflowMeterageNode)) {
            throw new ServiceException("您未设置流程，请联系管理员");
        }
        // 任务uuid
        String uuid = IdUtils.simpleUuid();
        // 设置 标段名称，项目名称，单位名称
        ProInstitution bid = institutionMapper.getModelByInnerCode(model.getInstitutionCode());
        model.setInstitutionName(bid.getInstitutionName());
        ProProject project = projectMapper.selectProProjectByProjectId(bid.getProjectId());
        model.setProjectId(project.getProjectId());
        model.setProjectName(project.getProjectName());
        ProCompany company = companyMapper.selectProCompanyByCompanyId(bid.getCompanyId());
        model.setCompanyName(company.getCompanyName());
        String applyName = "";
        if (StringUtils.isEmpty(bid.getReportCode())) {
            applyName = bid.getInnerCode() + DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, model.getDate()) + "形象进度";
        } else {
            applyName = bid.getReportCode() + DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, model.getDate()) + "形象进度";
        }
        model.setApplyName(applyName);
        // 设置当前部门和用户名称
        model.setCurrentDeptName(loginUser.getDept().getDeptName());
        model.setCurrentUser(loginUser.getUserName());
        model.setCurrentDept(loginUser.getDeptId());
        model.setCurrentUserName(loginUser.getNickName());
        model.setCreateBy(loginUser.getUserName());
        model.setCreateTime(DateUtils.getNowDate());
        model.setUuid(uuid);
        model.setWorkflowUuid(workflowMeterageNode.getWorkflowUuid());
        masterMapper.insert(model);
        // 添加明细
        PlanProfileBoq search = new PlanProfileBoq();
        search.setInstitutionCode(model.getInstitutionCode());
        List<PlanProfileBoq> boqList = planProfileBoqMapper.selectModelList(search);
        if (boqList.size() == 0) {
            throw new ServiceException("请联系管理员设置标段形象清单");
        }
        List<PlanProfileScheduleDetail> detailList = new ArrayList<>();
        for (PlanProfileBoq boq : boqList) {
            PlanProfileScheduleDetail detail = createDetail(boq, model.getMasterId(), loginUser);
            detailList.add(detail);
        }
        detailMapper.insertBatch(detailList);
        // 创建流程
        workflowTaskService.createTask(uuid, Constants.WORKFLOW_TYPE_PROFILE, Constants.MENU_TYPE_PROFILE_OVERALL, loginUser, workflowMeterageNode);
        return 1;
    }

    /**
     * 批量删除
     *
     * @param ids 主键集合
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteByIds(Integer[] ids) {
        for (int i = 0; i < ids.length; i++) {
            // 查找主表信息
            PlanProfileScheduleMaster master = masterMapper.getModelById(ids[i]);
            String uuid = master.getUuid();
            // 删除主表信息
            masterMapper.delete(ids[i]);
            // 删除流程
            workflowTaskService.deleteTask(uuid);
            // 删除消息
            messageService.deleteByUuid(uuid);
            // 删除明细
            detailMapper.deleteByMasterId(master.getMasterId());
        }
        return 1;
    }

    /**
     * 修改明细
     *
     * @param model 形象进度明细
     * @return 结果
     */
    @Override
    public int updateDetail(PlanProfileScheduleDetail model) {
        return detailMapper.update(model);
    }

    /**
     * 传送
     *
     * @param delivery 传送对象
     * @return 结果
     */
    @Override
    public int delivery(WorkflowTaskDelivery delivery) {
        // 当前登录用户
        SysUser loginUser = userMapper.selectUserById(SecurityUtils.getUserId());
        // 主表处理 修改当前部门和当前用户
        PlanProfileScheduleMaster master = masterMapper.getModelByUuid(delivery.getTaskUuid());
        // 传送至哪个用户，非当前登录用户
        SysUser deliveryUser = userMapper.selectUserByUserName(delivery.getUser());
        master.setCurrentDept(deliveryUser.getDeptId());
        master.setCurrentDeptName(deliveryUser.getDept().getDeptName());
        master.setCurrentUser(deliveryUser.getUserName());
        master.setCurrentUserName(deliveryUser.getNickName());
        masterMapper.update(master);
        // 传送明细
        deliveryDetail(master, loginUser, deliveryUser);
        // 流程处理
        workflowTaskService.deliveryTask(delivery, loginUser, deliveryUser);
        // 消息处理
        messageService.handleDeliveryMessage(master.getUuid(), loginUser.getUserName());
        messageService.createDeliveryMessage(
                master.getUuid(),
                deliveryUser.getUserName(),
                "/plan/scheduleProfile",
                "由" + loginUser.getNickName() + "传送的形象进度",
                loginUser.getUserName());
        return 1;
    }

    /**
     * 传送明细
     *
     * @param master 主表对象
     * @param loginUser 当前登陆用户对象
     * @param deliveryUser 传送至用户
     */
    private void deliveryDetail(PlanProfileScheduleMaster master, SysUser loginUser, SysUser deliveryUser) {
        PlanProfileScheduleDetail search = new PlanProfileScheduleDetail();
        search.setMasterId(master.getMasterId());
        search.setUser(loginUser.getUserName());
        // 先删除传送至用户下的数据
        detailMapper.deleteByUser(master.getMasterId(), deliveryUser.getUserName());
        // 当前登录用户下的数据
        List<PlanProfileScheduleDetail> details = detailMapper.selectModelList(search);
        for (PlanProfileScheduleDetail detail : details) {
            detail.setDept(deliveryUser.getDeptId());
            detail.setDeptName(deliveryUser.getDept().getDeptName());
            detail.setUser(deliveryUser.getUserName());
            detail.setUserName(deliveryUser.getNickName());
        }
        // 批量插入
        if (details.size() > 0) {
            detailMapper.insertBatch(details);
        }
    }


    /**
     * 创建形象进度明细
     *
     * @param boq 形象清单
     * @param masterId 主表主键
     * @param user 用户
     * @return 形象进度明细
     */
    private PlanProfileScheduleDetail createDetail(PlanProfileBoq boq, int masterId, SysUser user) {
        PlanProfileScheduleDetail detail = new PlanProfileScheduleDetail();
        detail.setMasterId(masterId);
        detail.setInstitutionBoqCode(boq.getInstitutionBoqCode());
        detail.setBoqCode(boq.getBoqCode());
        detail.setBoqName(boq.getBoqName());
        detail.setParentCode(boq.getParentCode());
        detail.setAncestors(boq.getAncestors());
        detail.setOrderNum(boq.getOrderNum());
        detail.setLevel(boq.getLevel());
        detail.setLeafNode(boq.getLeafNode());
        detail.setUnit(boq.getUnit());
        if (Constants.YES.equals(boq.getLeafNode())) {
            detail.setAmount(BigDecimal.ZERO);
            detail.setTotal(BigDecimal.ZERO);
            detail.setIsEdit(Constants.NO);
        }
        detail.setDept(user.getDeptId());
        detail.setDeptName(user.getDept().getDeptName());
        detail.setUser(user.getUserName());
        detail.setUserName(user.getNickName());
        detail.setCreateBy(user.getUserName());
        detail.setCreateTime(DateUtils.getNowDate());
        return detail;
    }

}
